import java.io.*;
import java.util.Map;

/**
 * 
 * @author Jonathan Hsu, Seth Mielke
 * 
 * @modified 8/6/11
 * 
 */
public class OpLoad extends Operation {

	public OpLoad(Word[] register, Word[] memory, FileReader programIn,
			FileWriter programOut) {
		super(register, memory, programIn, programOut);
	}

	/**
	 * This operation executes the load of the contents at S(x) where x is an
	 * index, into the register r.
	 * 
	 * @param pc
	 *            is the program counter, which holds the location of the next
	 *            instruction to be executed
	 * @param traceTable
	 *            is the table that holds the values of of registers and memory
	 *            before and after each instruction execution
	 * @return integer value of the program counter which indicates the location
	 *         of instruction to execute next.
	 * @throws IOException
	 */
	public int exec(int pc, Map<String, Word> traceTable) throws IOException {
		int r = memory[pc].r();
		int sx = memory[pc].s() + memory[pc].x();
		if (memory[pc].u1() == 0 && memory[pc].u2() == 0) {
			if (sx > 255 || sx < 0) {
				programOut.write('\n'
						+ "Out of bounds error at memory location "
						+ String.format("%02x", pc) + '\n');
				return pc + 1;
			} else {
				traceTable.put("Before: Register #" + Integer.toString(r),
						register[r].copy());
				traceTable.put("Before: Memory Location "
						+ String.format("%02x", sx).toUpperCase(), memory[sx].copy());
				
				register[r] = memory[sx].copy();
				traceTable.put("After: Register #" + Integer.toString(r),
						register[r]);
				traceTable.put("After: Memory Location "
						+ String.format("%02x", sx).toUpperCase(), memory[sx]);
				return pc + 1;
			}
		} else {
			programOut.write('\n' + "U1 or U2 not valid at "
					+ String.format("%02x", pc) + " resulting in a no-op."
					+ '\n');
			return pc + 1;
		}
	}
}
